/*********************************************************************
 * // 使用示例：
 * 
 *  #include <atomic>
 *  #include <thread>
 *  
 *  #include <hude/base/log.hpp>
 *  #include <hude/base/hex.hpp>
 *  #include <hude/aio/epoll.hpp>
 *  
 *  #include "test/test.hpp"
 *  
 *  #include <hal/real/serialport/serialport.hpp>
 *  
 *  namespace test
 *  {
 *      using namespace hude;
 *      using namespace hude::aio;
 *      using namespace hude::utils;
 *  
 *      //--------------------------------------------------------------------------------
 *      struct case_epoll_t : public case_t
 *      {
 *          enum : size_t { emCOUNT = 5000U, emINTERVAL = 2U };
 *  
 *          using sport_t    = muses::sport_t;
 *          using epoll_t    = hude::aio::epoll_t<>;
 *  
 *          std::atomic< bool >    running_;
 *          sport_t                sport_;
 *          epoll_t                epoll_;
 *  
 *          case_epoll_t() :
 *              running_( true ), epoll_( false )
 *          {
 *          }
 *  
 *          bool run() override
 *          {
 *              auto tty = "/dev/ttyUSB0";
 *  
 *              if( ! sport_.open( tty ) ||
 *                  ! sport_.settings( 115200U ) )
 *              {
 *                  log_err( "open serial port: %s", tty );
 *  
 *                  return false;
 *              }
 *  
 *              auto cb_sport = [this]( const epoll_t::event_t& event )
 *              {
 *                  hude::buffer_t buffer( 1024 );
 *  
 *                  auto capacity = buffer.size();
 *  
 *                  if( event.events & epoll_t::evt_t::emEPOLLIN )
 *                  {
 *                      size_t count = 0;
 *  
 *                      while( count < capacity )
 *                      {
 *                          auto ret = sport_.read( (char*)&(buffer[count]), capacity - count );
 *  
 *                          if( ret > 0 )
 *                          {
 *                              count += ret;
 *                          } else {
 *                              break;
 *                          }
 *                      }
 *  
 *                      buffer.resize( count );
 *  
 *                      log_dug( "input data: %d(%s)", count, to_hex( buffer, count ).c_str() );
 *                  } else {
 *                      log_dug( "not input event: %#x", event.events );
 *                  }
 *              };
 *  
 *              if( ! epoll_.create() )
 *              {
 *                  log_err( "create epoll." );
 *                  return false;
 *              }
 *  
 *              epoll_.add( sport_.handle() );
 *  
 *              auto th_send = std::thread( [this]()
 *              {
 *                  std::this_thread::sleep_for( std::chrono::milliseconds( 1U ) );
 *  
 *                  buffer_t buffer{ 0xff, 0, 0, 0, 0, 0, 0, 0 };
 *  
 *                  uint32_t* index = (uint32_t*)( &(buffer[4]) );
 *  
 *                  for( auto i = 0; i < emCOUNT; ++i )
 *                  {
 *                      log_dug( "write sport: %u(%s), times(%d)", buffer.size(), to_hex( buffer ).c_str(), i );
 *  
 *                      *index = i;
 *  
 *                      sport_.write( &(buffer[0]), buffer.size() );
 *  
 *                      std::this_thread::sleep_for( std::chrono::milliseconds( emINTERVAL ) );
 *                  }
 *  
 *                  std::this_thread::sleep_for( std::chrono::milliseconds( 3000U ) );
 *  
 *                  running_ = false;
 *              });
 *  
 *              while( running_ )
 *              {
 *                  epoll_.wait( cb_sport, 100U );
 *              }
 *  
 *              th_send.join();
 *  
 *              return true;
 *          }
 *      };
 *  
 *      //--------------------------------------------------------------------------------
 *      TEST_CASE_ADD( "epoll", case_epoll_t, true );
 *  
 *  } // namespace test
 * 
 ********************************************************************************************/

#ifndef __epoll_kenny_kfjiweur89u83r33e3e__
#define __epoll_kenny_kfjiweur89u83r33e3e__

#if defined( _WIN32 ) || defined( _WIN64 )
#  include <winsock2.h>

#  define EPOLLIN 1
#  define EPOLLOUT 4
#  define EPOLLPRI 8
#  define EPOLLERR 0x10
#  define EPOLLHUP 0x20
#  define EPOLLET 0x100
#  define EPOLLONESHOT 0x200
#else
#  include <poll.h>
#  include <errno.h>
#  include <fcntl.h>
#  include <unistd.h>
#  include <sys/socket.h>
#  include <sys/epoll.h>
#endif

#include <map>
#include <mutex>
#include <functional>
#include <hude/base/base_type.hpp>

namespace hude
{
    namespace aio
    {
        /*********************************************************************
         * @brief handler_t 被监听句柄类型
         */
#if defined( _WIN32 ) || defined( _WIN64 )
        using handler_t = uintptr_t;
#else //defined( _WIN32 ) || defined( _WIN64 )
        using handler_t = intptr_t;
#endif //defined( _WIN32 ) || defined( _WIN64 )

        /*********************************************************************
         * @brief epoll的事件类型标志
         */
        enum epoll_evt_t : uint32_t
        {
            emEPOLLIN      = EPOLLIN     , // ： 表示对应的文件描述符可以读（包括对端SOCKET正常关闭）；
            emEPOLLOUT     = EPOLLOUT    , // ： 表示对应的文件描述符可以写；
            emEPOLLPRI     = EPOLLPRI    , // ： 表示对应的文件描述符有紧急的数据可读（这里应该表示有带外数据到来）；
            emEPOLLERR     = EPOLLERR    , // ： 表示对应的文件描述符发生错误；
            emEPOLLHUP     = EPOLLHUP    , // ： 表示对应的文件描述符被挂断；
            emEPOLLET      = EPOLLET     , // ： 将EPOLL设为边缘触发(Edge Triggered)模式，这是相对于水平触发(Level Triggered)来说的。
            emEPOLLONESHOT = EPOLLONESHOT, // ： 只监听一次事件，当监听完这次事件之后，如果还需要继续监听这个socket的话，需要再次把这个socket加入到EPOLL队列里
            emEPOLLCLOSE   = 0xffff0000    // ： 自定义的事件，在用户指示epoll_plus_t关闭时让所有事件关注者收到该消息
        };

        /*********************************************************************
         * @brief 空锁
         */
        struct _null_mutex_t
        {
            void lock() const {}
            void unlock() const {}
        };

        /*********************************************************************
         * @brief select事件检测库针对事件处理的加强版
         */
        template< typename _user = void_t, uint_t _count = 1024U, typename _mutex = _null_mutex_t >
        class select_plus_t
        {
        public:
            using this_t        = select_plus_t< _user, _count, _mutex >;
            using user_t        = _user;
            using mutex_t       = _mutex;
            using autolock_t    = std::lock_guard< mutex_t >;
            using evt_t         = epoll_evt_t;
            using cb_event_t    = std::function< void( uint32_t, user_t& ) >;
            using item_t        = std::tuple< cb_event_t, user_t >;
            using entry_t       = std::tuple< uint32_t, item_t >;

        public:
            /*********************************************************************
             * @brief select_plus_t()
             */
            select_plus_t() {}

            /*********************************************************************
             * @brief select_plus_t()
             * @param init: 构造时是否尝试让select启动
             */
            ~select_plus_t()
            {
                this->clear();
            }

            /*********************************************************************
             * @brief select的创建
             */
            inline bool create() { return true; }

            /*********************************************************************
             * @brief select的关闭
             */
            inline void close() {}

            /*********************************************************************
             * @brief select的状态
             */
            inline operator bool() const { return true; }

            /*********************************************************************
             * @brief 加入让select监听的事件
             */
            inline int add( handler_t fd, cb_event_t cb, user_t user, uint32_t evt = evt_t::emEPOLLIN )
            {
                autolock_t _al( mutex_ );

                auto itr = map_event_.find( fd );

                if( itr == map_event_.end() )
                {
                    map_event_.emplace( fd, entry_t( evt, item_t( cb, user ) ) );
                } else {
                    itr->second = entry_t( evt, item_t( cb, user ) );
                }

                return 0;
            }

            /*********************************************************************
             * @brief 修改让select监听的事件
             */
            inline int mod( handler_t fd, cb_event_t cb, user_t user, uint32_t evt = evt_t::emEPOLLIN )
            {
                autolock_t _al( mutex_ );

                auto itr = map_event_.find( fd );

                if( itr != map_event_.end() )
                {
                    itr->second = entry_t( evt, item_t( cb, user ) );

                    return 0;
                }

                return -1;
            }

            /*********************************************************************
             * @brief 删除让select监听的事件
             */
            inline int del( handler_t fd )
            {
                autolock_t _al( mutex_ );

                auto itr = map_event_.find( fd );

                if( itr != map_event_.end() )
                {
                    map_event_.erase( itr );

                    return 0;
                }

                return -1;
            }

            /*********************************************************************
             * @brief 删除所有监听的事件
             */
            inline void clear()
            {
                std::map< handler_t, entry_t > tmp;
                
                {
                    autolock_t _al( mutex_ );

                    std::swap( tmp, map_event_ );
                }

                for( auto& i : tmp)
                {
                    auto& item = std::get<1>( i.second );

                    std::get<0>( item )( static_cast< uint32_t >( epoll_evt_t::emEPOLLCLOSE ), std::get<1>( item ) );
                }
            }

            /*********************************************************************
             * @brief 获得select监听的事件关注者数量
             */
            inline std::size_t size() const
            {
                autolock_t _al( mutex_ );

                return map_event_.size();
            }

            /*********************************************************************
             * @brief 获得select监听的事件关注者数量是否为空
             */
            inline bool empty() const
            {
                autolock_t _al( mutex_ );

                return map_event_.empty();
            }

            /*********************************************************************
             * @brief 加入或覆盖让select监听的事件
             */
            inline int push( handler_t fd, cb_event_t cb, user_t user = user_t{}, uint32_t evt = evt_t::emEPOLLIN )
            {
                return add( fd, cb, user, evt );
            }

            /*********************************************************************
             * @brief 删除让select监听的事件
             */
            inline int pop( handler_t fd ) { return del( fd ); }

            /*********************************************************************
             * @brief 等待select事件
             */
            inline int wait( size_t timeout = 3000U )
            {
                auto cb_set = [=]( fd_set& fs, evt_t evt ) -> void
                {
                    autolock_t _al( mutex_ );

                    FD_ZERO( &fs );

                    for( const auto& i : map_event_ )
                    {
                        if( evt == 0U || evt & std::get<0>( i.second ) )
                        {
                            FD_SET( i.first, &fs );
                        }
                    }
                };

                auto cb_evt = [=]( fd_set& fs, evt_t evt ) -> void
                {
                    std::list< std::tuple< handler_t, entry_t > > evts;

                    {
                        autolock_t _al( mutex_ );

                        for( auto& i : map_event_ )
                        {
                            if( ( std::get<0>( i.second ) & evt ) && FD_ISSET( i.first, &fs ) )
                            {
                                evts.push_back( std::make_tuple( i.first, i.second ) );
                            }
                        }
                    }

                    for( auto& i : evts )
                    {
                        item_t& item = std::get<1>( std::get<1>( i ) );
                        cb_event_t cb = std::get<0>( item );

                        auto last = std::chrono::system_clock::now();

                        cb( (uint32_t)evt, std::get<1>( item ) );

                        auto time = std::chrono::system_clock::now();

                        if( time > last + std::chrono::milliseconds( 50U ) )
                        {
                            auto ms = std::chrono::duration_cast< std::chrono::milliseconds>(time - last).count();
                            log_war( "AIO: the time too long of event comsume: %zu ms", ms );
                        }
                    }
                };

                fd_set r, w, e;

                cb_set( r, evt_t::emEPOLLIN );
                cb_set( w, evt_t::emEPOLLOUT );
                cb_set( e, evt_t::emEPOLLERR );

                struct timeval st;
                st.tv_sec = timeout / 1000;
                st.tv_usec = ( timeout % 1000 ) * 1000;

                auto ret = ::select( _count + 1, &r, &w, &e, &st );

                // log_tra( "select() = %d", ret );

                if( ret > 0 )
                {
                    cb_evt( r, evt_t::emEPOLLIN );
                    cb_evt( w, evt_t::emEPOLLOUT );
                    cb_evt( e, evt_t::emEPOLLERR );
                }

                return ret;
            }

            /*********************************************************************
             * @brief 遍历select监听的所有事件关注者
             */
            inline std::size_t foreach( std::function< bool( handler_t, item_t& ) > cb )
            {
                std::size_t ret = 0;

                autolock_t _al( mutex_ );

                for( auto& i : map_event_ )
                {
                    if( cb( i.first, std::get<1>( i.second ) ) ) 
                    {
                        ret += 1;
                    } else {
                        break;
                    }
                }

                return ret;
            }

        private:
            mutable mutex_t mutex_;

            std::map< handler_t, entry_t > map_event_;
        };

#if defined( _WIN32 ) || defined( _WIN64 )
        /*********************************************************************
         * @brief socket 初始化
         */
        struct socket_initer_t
        {
            socket_initer_t()
            {
                WSADATA wsaData;
                WSAStartup(MAKEWORD(2, 2), &wsaData);
            }

            ~socket_initer_t()
            {
                WSACleanup();
            }

            static std::shared_ptr< socket_initer_t > get_obj()
            {
                static std::shared_ptr< socket_initer_t > ptr{ new socket_initer_t };

                return ptr;
            }
        };
#else //defined( _WIN32 ) || defined( _WIN64 )
        /*********************************************************************
         * @brief socket 初始化
         */
        struct socket_initer_t
        {
            socket_initer_t()
            {
            }

            ~socket_initer_t()
            {
            }

            static std::shared_ptr< socket_initer_t > get_obj()
            {
                static std::shared_ptr< socket_initer_t > ptr{ new socket_initer_t };

                return ptr;
            }
        };

        /*********************************************************************
         * @brief epoll事件检测库，是Linux内核epoll机制的1：1封装
         */
        template< uint_t _count = 1U >
        class epoll_t
        {
        public:
            enum { emCOUNT = _count };

            /*********************************************************************
             * @brief epoll的操作符
             */
            enum struct op_t : int
            {
                emADD = EPOLL_CTL_ADD,
                emMOD = EPOLL_CTL_MOD,
                emDEL = EPOLL_CTL_DEL
            };

            /*********************************************************************
             * @brief epoll的事件类型标志
             */
            typedef epoll_evt_t evt_t;

            /*********************************************************************
             * @brief epoll的事件对象
             */
            typedef epoll_event event_t;

            /*********************************************************************
             * @brief epoll的事件回调
             */
            typedef std::function< void( const event_t& ) > cb_event_t;

        public:
            /*********************************************************************
             * @brief epoll对象构造器
             * @param init指定构造对象时是否直接初始化
             */
            epoll_t( bool init = false ) : fd_( 0 ) { if( init ) { create(); } }

            /*********************************************************************
             * @brief epoll对象的析构函数
             */
            ~epoll_t() { close(); }

            /*********************************************************************
             * @brief epoll对象的初始化函数
             */
            inline bool create();

            /*********************************************************************
             * @brief epoll对象的操作函数
             * @param op_t 类型为操作符，取值可以是增加/修改/删除
             * @param handler_t 类型为流文件句柄，epoll将对该文件句柄进行事件监听
             * @param uintptr_t 类型为用户私用数据指针，用户可使用该指针传递私用数据到事件处理回调中
             * @param uint32_t 类型为事件类型标志，指定epoll监听的事件类型
             * @return epoll操作返回值， 0为正常，非0错误
             */
            inline int  ctrl( op_t, handler_t, uintptr_t user = 0, uint32_t = emEPOLLET | emEPOLLIN );

            /*********************************************************************
             * @brief epoll的开始监听函数
             * @param cb_event_t 类型为事件回调对象
             * @param size_t 类型为监听时长，单位ms
             * @return epoll监听过程发生事件的事件数量， >0时为事件数量，==0时为超时，<0时错误
             */
            inline int  wait( cb_event_t, size_t = 3000UL );

            /*********************************************************************
             * @brief epoll的ctrl函数的增加操作的简化调用，具体可参考ctrl操作
             */
            inline int  add( handler_t handle, uintptr_t user = 0U, uint32_t evts = emEPOLLET | emEPOLLIN ) { return this->ctrl( op_t::emADD, handle, user, evts ); }

            /*********************************************************************
             * @brief epoll的ctrl函数的修改操作的简化调用，具体可参考ctrl操作
             */
            inline int  mod( handler_t handle, uintptr_t user = 0U, uint32_t evts = emEPOLLET | emEPOLLIN ) { return this->ctrl( op_t::emMOD, handle, user, evts ); }

            /*********************************************************************
             * @brief epoll的ctrl函数的删除操作的简化调用，具体可参考ctrl操作
             */
            inline int  del( handler_t handle ) { return this->ctrl( op_t::emDEL, handle, 0U, 0U ); }

            /*********************************************************************
             * @brief 返回epoll的原始句柄
             */
            inline void  close();

            /*********************************************************************
             * @brief 返回epoll的原始句柄
             */
            inline int  handle() const { return fd_; }

            /*********************************************************************
             * @brief 返回epoll是否初始化
             */
            operator bool() const { return fd_ >= 0; }

        private:
            handler_t fd_; //epoll标识符
            struct epoll_event events_[emCOUNT]; //事件集合

        private:
            epoll_t( const epoll_t& ) = delete;
            epoll_t& operator=( const epoll_t& ) = delete;
            epoll_t& operator=( epoll_t&& ) = delete;

        };

        /*********************************************************************
         * @brief epoll事件检测库针对事件处理的加强版
         */
        template< typename _user = void_t, uint_t _count = 1024U, typename _mutex = _null_mutex_t >
        class epoll_plus_t
        {
        public:
            using base_t       = epoll_t< _count >;
            using user_t       = _user;
            using mutex_t      = _mutex;
            using autolock_t   = std::lock_guard< mutex_t >;
            using evt_t        = epoll_evt_t;
            using event_t      = typename base_t::event_t;
            using cb_event_t   = std::function< void( uint32_t, user_t& ) >;
            using item_t       = std::tuple< cb_event_t, user_t >;

        public:
            /*********************************************************************
             * @brief epoll_plus_t()
             * @param init: 构造时是否尝试让epoll启动
             */
            epoll_plus_t( bool init = false ) : epoll_( init ) {}

            /*********************************************************************
             * @brief epoll_plus_t()
             * @param init: 构造时是否尝试让epoll启动
             */
            ~epoll_plus_t()
            {
                autolock_t _al( mutex_ );

                for( auto& i : map_event_ )
                {
                    std::get<0>( i.second )( static_cast< uint32_t >( epoll_evt_t::emEPOLLCLOSE ), std::get<1>( i.second ) );
                }
            }

            /*********************************************************************
             * @brief epoll的原生方法
             */
            base_t* operator->() { return &epoll_; }
            const base_t* operator->() const { return &epoll_; }

            /*********************************************************************
             * @brief epoll的创建
             */
            inline bool create() { return epoll_.create(); }

            /*********************************************************************
             * @brief epoll的关闭
             */
            inline void close() { epoll_.close(); }

            /*********************************************************************
             * @brief epoll的状态
             */
            inline operator bool() const { return epoll_.operator bool(); }

            /*********************************************************************
             * @brief 加入让epoll监听的事件
             */
            inline int add( handler_t fd, cb_event_t cb, user_t user,
                uint32_t evt = evt_t::emEPOLLET | evt_t::emEPOLLIN )
            {
                autolock_t _al( mutex_ );

                auto itr = map_event_.find( fd );

                if( itr == map_event_.end() )
                {
                    auto pos = map_event_.emplace( fd, item_t( cb, user ) );

                    int ret = epoll_.add( fd, (uintptr_t)(void*)&(pos.first->second), evt );

                    if( ret != 0 )
                    {
                        map_event_.erase( pos.first );
                    }

                    return ret;
                } else {
                    itr->second = item_t( cb, user );

                    int ret = epoll_.mod( fd, (uintptr_t)(void*)&(itr->second), evt );

                    return ret;
                }
            }

            /*********************************************************************
             * @brief 修改让epoll监听的事件
             */
            inline int mod( handler_t fd, cb_event_t cb, user_t user,
                uint32_t evt = evt_t::emEPOLLET | evt_t::emEPOLLIN )
            {
                autolock_t _al( mutex_ );

                auto itr = map_event_.find( fd );

                if( itr != map_event_.end() )
                {
                    itr->second = item_t( cb, user );

                    int ret = epoll_.mod( fd, (uintptr_t)(void*)&(itr->second), evt );

                    return ret;
                }
            }

            /*********************************************************************
             * @brief 删除让epoll监听的事件
             */
            inline int del( handler_t fd )
            {
                autolock_t _al( mutex_ );

                int ret = -123;

                auto itr = map_event_.find( fd );

                if( itr != map_event_.end() )
                {
                    ret = epoll_.del( fd );

                    map_event_.erase( itr );
                }

                return ret;
            }

            /*********************************************************************
             * @brief 删除所有监听的事件
             */
            void clear()
            {
                std::map< handler_t, item_t > tmp;

                {
                    autolock_t _al( mutex_ );
                    std::swap( tmp, map_event_ );
                }

                for( auto& i : tmp )
                {
                    epoll_.del( i.first );
                    std::get<0>( i.second )( static_cast< uint32_t >( epoll_evt_t::emEPOLLCLOSE ), std::get<1>( i.second ) );
                }
            }

            /*********************************************************************
             * @brief 获得epoll监听的事件关注者数量
             */
            inline std::size_t size() const
            {
                autolock_t _al( mutex_ );

                return map_event_.size();
            }

            /*********************************************************************
             * @brief 获得epoll监听的事件关注者数量是否为空
             */
            inline bool empty() const
            {
                autolock_t _al( mutex_ );

                return map_event_.empty();
            }

            /*********************************************************************
             * @brief 加入或覆盖让epoll监听的事件
             */
            inline int push( handler_t fd, cb_event_t cb, user_t user = user_t{},
                uint32_t evt = evt_t::emEPOLLET | evt_t::emEPOLLIN )
            {
                return add( fd, cb, user, evt );
            }

            /*********************************************************************
             * @brief 删除让epoll监听的事件
             */
            inline int pop( handler_t fd ) { return del( fd ); }

            /*********************************************************************
             * @brief 等待epoll事件
             */
            inline int wait( size_t timeout = 3000U )
            {
                auto cb = []( const typename base_t::event_t& e ) -> void
                {
                    auto last = std::chrono::system_clock::now();

                    auto ptr = (item_t*)e.data.ptr;
                    std::get<0>( *ptr )( static_cast< uint32_t >( e.events ), std::get<1>( *ptr ) );

                    auto time = std::chrono::system_clock::now();

                    if( time > last + std::chrono::milliseconds( 50U ) )
                    {
                        auto ms = std::chrono::duration_cast< std::chrono::milliseconds>(time - last).count();
                        log_war( "AIO: the time too long of event comsume: %zu ms", ms );
                    }
                };

                return epoll_.wait( cb, timeout );
            }

            /*********************************************************************
             * @brief 遍历epoll监听的所有事件关注者
             */
            inline std::size_t foreach( std::function< bool( handler_t, item_t& ) > cb )
            {
                std::size_t ret = 0;

                autolock_t _al( mutex_ );

                for( auto& i : map_event_ )
                {
                    if( cb( i.first, i.second ) ) 
                    {
                        ret += 1;
                    } else {
                        break;
                    }
                }

                return ret;
            }

        private:
            mutable mutex_t mutex_;

            base_t epoll_;
            std::map< handler_t, item_t > map_event_;
        };

        //--------------------------------------------------------------------------------
        template< uint_t _count >
        inline bool epoll_t< _count >::create()
        {
            fd_ = epoll_create( emCOUNT );

            // log_dug( "\t epoll_create( %u ) == %d", emCOUNT, fd_ );

            return fd_ >= 0;
        }

        //--------------------------------------------------------------------------------
        template< uint_t _count >
        inline void epoll_t< _count >::close()
        {
            // log_dug( "\t epoll_close( %d )", fd_ );

            ::close( fd_ ); fd_ = -1;
        }

        //--------------------------------------------------------------------------------
        template< uint_t _count >
        inline int epoll_t< _count >::ctrl( op_t op, handler_t fd, uintptr_t user, uint32_t evts )
        {
            struct epoll_event event;

            event.events = evts;

            if( user == 0 )
                event.data.fd = fd;
            else
                event.data.u64 = user;

            auto ret = epoll_ctl( fd_, (int)op, fd, &event );

            return ret;
        }

        //--------------------------------------------------------------------------------
        template< uint_t _count >
        inline int epoll_t< _count >::wait( cb_event_t cb, size_t timeout )
        {
            if( fd_ > 0 )
            {
                // log_dug( "\t epoll_wait( %d, events, %u, %u )", fd_, emCOUNT, timeout );
                auto siz = epoll_wait( fd_, events_, emCOUNT, timeout );

                for( auto p = &(events_[0]); p < events_ + siz; ++p )
                {
                    cb( *p );
                }

                return siz;
            } else {
                return -1;
            }
        }
#endif //!defined( _WIN32 ) && !defined( _WIN64 )

    } // namespace aio
} // namespace nsPGL

#endif // __epoll_kenny_kfjiweur89u83r33e3e__